/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-04
 * V4.0
 */
package com.jphenix.kernel.objectpool.instancea;

import com.jphenix.driver.serialno.FSN;
import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.kernel.objectpool.exception.ObjectPoolException;
import com.jphenix.kernel.objectpool.interfaceclass.IObjectElement;
import com.jphenix.kernel.objectpool.interfaceclass.IObjectPool;
import com.jphenix.share.lang.SListMap;
import com.jphenix.share.util.DebugUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.serialno.ISN;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * 对象池管理类
 * 
 * 采用父类继承的方法，简化了具有池功能模块的开发难度
 * 剔除掉了与类功能无关的参数构造方法
 * 池元素分为两种，1公共池元素 2私有池元素
 * 主要调用方法：getObjectInstance(type,pk)
 * type为元素类型，是必要参数 pk 为元素主键，在为空时，默认返回公共元素实例,在非空时返回私有元素实例
 * 
 * 必须实现方法：
 * initObjectElement(type,pk) 根据类型构造新的元素实例
 * checkElementError(element) 检查元素是否出错
 * 
 * 2018-09-10 资源占用超时，需要判断该资源是私有资源还是公有资源。如果是私有资源，则强制关闭。如果是公有资源，只发出警告 2019-01-25
 *            如果构造对象数量超过上限，只报错误日志，并不抛出异常，避免人为导致错误。 2019-04-24
 *            增加了配置文件参数datamanager_no_out_log,可以屏蔽数据库连接池输出日志 2019-06-26 修改了序列号生成器的构造方法
 * 2019-11-06 如果元素的getMaxObjectCount()小于0，则不控制获取实例上限 2020-01-10
 *            将轮训检测是否占用或空闲超时时间从1秒该为30秒，避免频繁输出警告日志
 * 2021-03-17 整理了代码格式
 * 
 * @author 刘虻
 * 2006-8-12 16:58:09
 */
@ClassInfo({ "2021-03-03 15:52", "对象池管理类" })
public abstract class ObjectPool extends ABase implements IObjectPool {

  protected long initObjectTimeOut = 60000; // 初始化类实例超时时间
  protected int timeAround = 30000; // 轮训检查间隔时间
  protected int overflowTryCount = 10; // 溢出后尝试恢复次数
  protected int overflowWaitTime = 10000; // 溢出后尝试恢复间隔时间
  protected int state = 0; // 池运行状态 1停止 0正常 2运行中
  private ISN sn = null; // 序列号生成器
  protected boolean outLog = true; // 是否输出日志

  // 对象池容器 (key type) (value (Hashtable key pk value Hashtable:ObjectElement
  // key:propKey value:propValue))
  protected SListMap<SListMap<IObjectElement>> objectPoolHasm = null;
  protected ObjectPoolRootThread oprt = null; // 构造服务线程

  /**
   * 初始化类线程
   * @author 刘虻
   * 2007-8-20下午05:52:39
   */
  protected class InitObjectThread extends Thread {

    protected String         type      = null; // 类型标识
    protected String         pk        = null; // 类实例主键
    protected IObjectElement reElement = null; // 返回的类实例
    protected Exception      e         = null; // 执行发生异常

    /**
     * 构造函数
     * 2007-8-20下午05:53:18
     */
    public InitObjectThread(String type, String pk) {
      super("ObjectPool-InitObjectThread");
      this.type = type;
      this.pk = pk;
    }

    /**
     * 获取返回的类实例
     * @author 刘虻
     * 2007-8-20下午05:55:03
     * @return 返回的类实例
     */
    public IObjectElement getReElement() {
      return reElement;
    }

    /**
     * 获取异常
     * @author 刘虻
     * 2007-8-20下午05:56:39
     * @return 异常
     */
    public Exception getException() {
      return e;
    }

    /**
     * 覆盖方法
     * @author 刘虻
     * 2007-8-20下午05:54:49
     */
    @Override
    public void run() {
      try {
        reElement = initObjectElement(type, pk);
      } catch (Exception e) {
        this.e = e;
      }
    }
  }

  /**
   * 服务线程
   * @author 刘虻
   * 2007-7-5上午11:27:37
   */
  protected class ObjectPoolRootThread extends Thread {

    /**
     * 构造函数
     * 2007-7-5上午11:27:02
     */
    public ObjectPoolRootThread(ObjectPool ope) {
      super(getClassName() + "-ObjectPoolRootThread-" + ope.hashCode());
    }

    /**
     * 覆盖方法
     * @author 刘虻
     * 2007-7-5上午11:27:10
     */
    @Override
    public void run() {
      // 循环检查对象空闲／超时信息
      String pk; // 对象主键
      ObjectElement element; // 对象元素
      if (objectPoolHasm != null) {
        while (state != 1) {
          // 循环所有类型
          for (int i = 0; i < objectPoolHasm.size(); i++) {
            // 获得指定类型的池
            SListMap<IObjectElement> thisTypeHasm = objectPoolHasm.get(i);
            if (thisTypeHasm != null) {
              // 循环当前类型池中所有元素
              for (int j = 0; j < thisTypeHasm.size(); j++) {
                pk = thisTypeHasm.getKey(j);
                if (pk == null || pk.length() < 1) {
                  continue;
                }
                // 获取指定元素
                element = (ObjectElement) thisTypeHasm.get(j);
                if (element == null) {
                  // 移出该主键的元素
                  thisTypeHasm.remove(pk);
                } else {
                  if (element.isPossessTimeOut()) {
                    // 对象占用超时
                    if (element.isPrivate()) {
                      // 私有资源，直接强制断开
                      log.warning("The Private Object Use Time Out,Begin To Close Type:[" + element.getType() + "] PK:["
                          + element.getPK() + "] MaxLoad:[" + element.getMaxObjectCount() + "] ThisLoad:["
                          + thisTypeHasm.size() + "] Use Out Time:[" + element.getUseTimeOut() + "]", null);
                      // element.setPK(pk); //临时重设主键 私有连接对象，本身就又主键，不应该在这里重新设置新的主键
                      if (element.getPK() == null || element.getPK().length() < 1) {
                        element.setPK(pk); // 不应该走到这里
                      }
                      closeElement(element); // 执行关闭
                      continue;
                    } else {
                      // 公共资源，只能写入警告日志，不能强制断开，否则会影响到其它获取到该公共资源的程序
                      log.warning("The Public Object Use Time Out Type:[" + element.getType() + "] PK:["
                          + element.getPK() + "] MaxLoad:[" + element.getMaxObjectCount() + "] ThisLoad:["
                          + thisTypeHasm.size() + "] Use Out Time:[" + element.getUseTimeOut() + "]", null);
                      continue;
                    }
                  }
                  if (element.isNotUseTimeOut()) {
                    // 空闲超时
                    // 判断为对象空闲超时
                    if (outLog) {
                      log("The Object Not Used Time Out,Begin To CLose Type:[" + element.getType() + "] PK:["
                          + element.getPK() + "] MaxLoad:[" + element.getMaxObjectCount() + "] ThisLoad:["
                          + thisTypeHasm.size() + "] Free Out Time:[" + element.getFreeTimeOut() + "]");
                    }
                    element.setPK(pk); // 临时重设主键
                    closeElement(element); // 执行关闭
                    continue;
                  }
                }
              }
            }
          }
          try {
            // 间隔轮训
            Thread.sleep(getTimeAround());
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
        state = 0; // 线程停止
      }
    }
  }

  /**
   * 构造函数
   * @author 刘虻
   * 2006-8-12 16:58:09
   */
  public ObjectPool() {
    super();
  }

  /**
   * 初始化一个新的类实例
   * @author 刘虻
   * @param type 类实例类型
   * @param pk   类实例主键
   * @return     初始化后的类实例
   * @throws Exception 初始化类实例时发生异常
   * 2006-8-12 17:36:48
   */
  protected abstract IObjectElement initObjectElement(String type, String pk) throws Exception;

  /**
   * 判断元素是否错误
   * @author 刘虻
   * @param element 元素
   * @return true 错误
   * 2006-8-13 12:06:18
   */
  protected abstract boolean checkElementError(IObjectElement element);

  /**
   * 获取有效的对象池容器
   * @author 刘虻
   * @return 有效的对象池容器
   * 2006-8-12 17:11:27
   */
  protected SListMap<SListMap<IObjectElement>> getObjectPoolMap() {
    if (objectPoolHasm == null) {
      objectPoolHasm = new SListMap<SListMap<IObjectElement>>();
    }
    return objectPoolHasm;
  }

  /**
   * 关闭池元素
   * @author 刘虻
   * @param element 池元素
   * @return 返回当前类实例
   * 2006-8-13 13:47:45
   */
  @Override
  public void closeElement(IObjectElement element) {
    if (objectPoolHasm == null) {
      // 中止元素
      element.terminat();
    } else {
      synchronized (objectPoolHasm) {
        if (element == null) {
          log.error("The Element Is Null Before To closeElement", null);
          return;
        }
        // 获取类型信息
        String type = element.getType();
        if (type == null) {
          log.error("Not Find The Element's Type Before To closeElement", null);
          return;
        }
        // 获取主键信息
        String pk = element.getPK();
        if (pk == null) {
          log.error("Not Find The Element's PK Before To closeElement", null);
          return;
        }
        // 输出日志
        doOutCloseInstance(element);
        // 获取到该类型下的容器
        SListMap<IObjectElement> typeMap = objectPoolHasm.get(type);
        if (typeMap != null) {
          // 从池中移出元素
          typeMap.remove(pk);
        }
        // 中止元素
        element.terminat();
      }
    }
  }

  /**
   * 根据对象元素类型获取有效的对象实例容器
   * @author 刘虻
   * @param type 对象元素类型
   * @return 有效的对象实例容器
   * 2006-8-12 17:17:01
   */
  protected SListMap<IObjectElement> getTypeObjectPool(String type) {
    SListMap<IObjectElement> reHasm = getObjectPoolMap().get(type);
    if (reHasm == null) {
      // 如果容器为空，则构造一个新的放进去
      reHasm = new SListMap<IObjectElement>();
      getObjectPoolMap().put(type, reHasm);
    }
    return reHasm;
  }

  /**
   * 强制关闭一种类型的池元素 pk为空时关闭该类型所有元素
   * @author 刘虻
   * 2006-9-8下午04:42:39
   * @param type 元素类型
   * @param pk   元素主键
   */
  @Override
  public void closeElement(String type, String pk) {
    if (objectPoolHasm == null) {
      return;
    }
    IObjectElement element; // 对象元素
    List<String> typeList; // 类型序列
    if (type == null || type.length() < 1) {
      typeList = getAllTypeList();
    } else {
      typeList = new ArrayList<String>();
      typeList.add(type);
    }
    synchronized (objectPoolHasm) {
      SListMap<IObjectElement> typeHashMap;
      for (String ele : typeList) {
        // 获取指定类型元素容器
        typeHashMap = getTypeObjectPool(ele);
        if (pk == null) {
          for (int i = 0; i < typeHashMap.size(); i++) {
            pk = typeHashMap.getKey(i);
            // 获取元素
            element = typeHashMap.get(pk);
            if (element != null) {
              typeHashMap.remove(pk);
              element.terminat(); // 中止元素
            }
          }
        } else {
          // 获取制定对象元素
          element = typeHashMap.get(pk);
          if (element != null) {
            typeHashMap.remove(pk);
            element.terminat(); // 中止元素
          }
        }
      }
    }
  }

  /**
   * 根据主键获取所有类型的元素
   * @author 刘虻
   * @param pk 主键
   * @return 所有类型的元素序列
   * 2006-8-13 13:59:35
   */
  public List<IObjectElement> getAllTypeElementByPk(String pk) {
    // 构造返回值
    Vector<IObjectElement> reArrl = new Vector<IObjectElement>();
    if (objectPoolHasm == null || pk == null || pk.length() < 1) {
      return reArrl;
    }
    IObjectElement obj; // 元素
    for (int i = 0; i < objectPoolHasm.size(); i++) {
      // 从指定类型池中获取指定元素
      obj = objectPoolHasm.get(i).get(pk);
      if (obj != null) {
        // 放入返回容器
        reArrl.add(obj);
      }
    }
    return reArrl;
  }

  /**
   * 设置类实例
   * @author 刘虻
   * 2007-5-14下午12:51:28
   * @param objectElement 将要放入容器的类实例
   * @return 返回当前类实例
   */
  @Override
  public void setObjectInstance(IObjectElement objectElement) {
    if (objectElement == null || objectElement.getType() == null || objectElement.getPK() == null) {
      log.error("The Pool Element Value Is Null", null);
      return;
    }
    if (objectPoolHasm == null) {
      return;
    }
    objectElement.isPrivate(true); // 设置为私有，避免空闲时被别人用了
    // 获得指定类型的对象池容器
    SListMap<IObjectElement> thisTypeObjectPool = getTypeObjectPool(objectElement.getType());
    // 放入池
    thisTypeObjectPool.put(objectElement.getPK(), objectElement);
  }

  /**
   * 检测对象实例是否被释放 刘虻 2010-5-4 上午11:12:22
   * 
   * @param objectElement 指定对象实例
   * @throws Exception 对象占用超时
   */
  protected void checkReturn(IObjectElement objectElement) throws Exception {
    while (true) {
      if (!objectElement.isPossess()) {
        return;
      }
      if (objectElement.isPossessTimeOut()) {
        // 对象占用超时
        if (objectElement.isIgnoreException()) {
          // 直接抛出异常
          throw new ObjectPoolException(this, "The Object Type:[" + objectElement.getType() + "] PK:["
              + objectElement.getPK() + "] Possess Time Out:[" + objectElement.getUseTimeOut() + "]");
        }
        log.warning("The Object Type:[" + objectElement.getType() + "] PK:[" + objectElement.getPK()
            + "] Possess Time Out:[" + objectElement.getUseTimeOut() + "]", null);
        // 强制终止
        closeElement(objectElement);
        // 重新进行初始化
        initObjectElement(objectElement.getType(), objectElement.getPK());
        return;
      }
      Thread.sleep(100);
    }
  }

  /**
   * 获得对象实例
   * @author 刘虻
   * @param type 对象类型
   * @param pk   对象主键
   * @return 对象实例
   * @throws Exception 异常
   * 2006-8-12 17:06:51
   */
  @Override
  public IObjectElement getObjectInstance(String type, String pk) throws Exception {
    if (objectPoolHasm == null) {
      throw new ObjectPoolException(this, "The Pool Has Not init (objectPoolHasm is null)");
    }
    try {
      if (type == null || "".equals(type)) {
        // 没有获得对象类型
        throw new ObjectPoolException(this, "Not Find The Object Type type:[" + type + "] pk:[" + pk + "]");
      }
      // 获得指定类型的对象池容器
      SListMap<IObjectElement> thisTypeObjectPool = getTypeObjectPool(type);
      // 准备获取的对象池元素
      IObjectElement objectElement = null;
      if (pk != null && pk.length() > 0) {
        // 私有元素
        objectElement = thisTypeObjectPool.get(pk);
        if (objectElement == null) {
          // 初始化私有元素
          // 构造一个新的类
          try {
            // 构造一个新的类
            objectElement = getInitElement(type, pk, thisTypeObjectPool.size());
          } catch (Exception e) {
            log.error("getObjectInstance Error Type:[" + type + "] PK:[" + pk + "]", e);
          }
        } else {
          // 太他妈不凑巧了，这个对象正在上钟（洗脚用语，自己查），等到钟以后才能继续用
          if (objectElement.isPossess()) {
            checkReturn(objectElement);
          }
        }
        objectElement.isPrivate(true); // 标记为私有
        objectElement.refreshAction(); // 刷新元素
        doOutGetInstance(objectElement);
        return objectElement;
      }
      // 获取公共元素
      String key; // 当前对象主键
      for (int i = 0; i < thisTypeObjectPool.size(); i++) {
        // 循环池中所有元素
        key = thisTypeObjectPool.getKey(i);
        objectElement = thisTypeObjectPool.get(key);
        if (objectElement == null) {
          thisTypeObjectPool.remove(key);
          log.error("The Element Of Pool Is Null", null);
          continue;
        }
        if (objectElement.isPossess() || objectElement.isPrivate()) {
          // 该元素为私有元素，正在使用中
          continue;
        }
        objectElement.refreshAction(); // 刷新元素
        doOutGetInstance(objectElement);
        return objectElement;
      }
      // 构造一个新的类
      try {
        // 构造一个新的类
        objectElement = getInitElement(type, pk, thisTypeObjectPool.size());
      } catch (Exception e) {
        log.error("getObjectInstance Error Type:[" + type + "] PK:[" + pk + "]", e);
      }
      if (objectElement == null) {
        throw new ObjectPoolException(this, "Not Find The Object Type:[" + type + "] PK:[" + pk + "]");
      }
      objectElement.refreshAction(); // 刷新元素信息
      thisTypeObjectPool.put(objectElement.getPK(), objectElement); // 放入指定类型的容器中
      doOutGetInstance(objectElement);
      return objectElement;
    } catch (Exception e) {
      throw new ObjectPoolException(this,
          "Get Instance Exception Type:[" + type + "] PK:[" + pk + "] :" + DebugUtil.outException(e));
    }
  }

  /**
   * 获得初始化后的元素 刘虻
   * 2010-5-4 下午02:08:13
   * @param type            类型
   * @param pk              主键
   * @param thisObjectCount 当前已经加载的对象总数
   * @return 初始化后的元素
   * @throws Exception 执行发生异常
   */
  @SuppressWarnings("deprecation")
  protected IObjectElement getInitElement(String type, String pk, int thisObjectCount) throws Exception {
    if (objectPoolHasm == null) {
      throw new ObjectPoolException(this, "The Pool Has Not init (objectPoolHasm is null)");
    }
    IObjectElement reElement = null; // 构造返回值
    doOutInit(type, pk); // 显示日志
    // 构造初始化线程
    InitObjectThread iot = new InitObjectThread(type, pk);
    iot.start();
    try {
      iot.join(getInitObjectTimeOut());
    } catch (Exception e) {
    }
    if (iot.isAlive()) {
      iot.stop();
    }
    if (iot.getException() != null) {
      iot.getException().printStackTrace();
      throw new ObjectPoolException(this, "Init Object Exception:" + DebugUtil.getExceptionMessage(iot.getException()));
    }
    if (iot.getReElement() == null) {
      throw new ObjectPoolException(this, "Init Object Time Out");
    } else {
      reElement = iot.getReElement();
    }
    if (reElement.getMaxObjectCount() > -1 && thisObjectCount >= reElement.getMaxObjectCount()) {
      // 不抛出异常，可以将就用
      error("Load Object Type:[" + type + "] PK:[" + pk + "] Overflow:[" + thisObjectCount + "] Max: ("
          + reElement.getMaxObjectCount() + ")");
    }
    try {
      if (checkElementError(reElement)) {
        throw new ObjectPoolException(this, "Get Init Object Error Type:[" + type + "] PK:[" + pk + "]");
      }
      if (pk == null || pk.length() < 1) {
        // 构造新主键
        pk = getSID();
      }
      // 获得指定类型的对象池容器
      SListMap<IObjectElement> thisTypeObjectPool = getTypeObjectPool(type);
      // 放入池中
      thisTypeObjectPool.put(pk, reElement);
      return reElement;
    } catch (Exception e) {
      e.printStackTrace();
    }
    throw new ObjectPoolException(this, "Load Object Overflow Type:[" + type + "] PK:[" + pk + "]");
  }

  /**
   * 显示关闭类实例
   * @author 刘虻
   * @param element 元素实例
   * 2006-8-12 18:19:54
   */
  protected void doOutCloseInstance(IObjectElement element) {
    if (outLog) {
      log("Close Instance <>  type:[" + element.getType() + "] pk:[" + element.getPK() + "] maxLoad:["
          + element.getMaxObjectCount() + "]");
    }
  }

  /**
   * 释放池元素
   * 注意：该方法只能由 ObjectElement调用
   * @author 刘虻
   * @param element 池元素
   * 2006-8-13 12:52:05
   */
  @Override
  public void freeElement(IObjectElement element) {
    if (element == null) {
      log.error("The Element Is Null Before To freeElement", null);
      return;
    }
    // 输出日志
    doOutFreeInstance(element);
  }

  /**
   * 显示返回类实例
   * @author 刘虻
   * @param element 元素实例
   * 2006-8-12 18:19:54
   */
  protected void doOutFreeInstance(IObjectElement element) {
    if (outLog) {
      log("Return Instance ┛  type:[" + element.getType() + "] pk:[" + element.getPK() + "] maxLoad:["
          + element.getMaxObjectCount() + "]");
    }
  }

  /**
   * 显示获取类实例
   * @author 刘虻
   * @param element 元素实例
   * 2006-8-12 18:19:54
   */
  protected void doOutGetInstance(IObjectElement element) {
    if (outLog) {
      log("Get Instance    ┓  type:[" + element.getType() + "] pk:[" + element.getPK() + "] maxLoad:["
          + element.getMaxObjectCount() + "]");
    }
  }

  /**
   * 显示初始化信息日志
   * @author 刘虻
   * @param type 元素类型
   * @param pk   元素主键
   * 2006-8-12 17:41:42
   */
  protected void doOutInit(String type, String pk) {
    if (outLog) {
      log("Init Instance ><  type:[" + type + "] pk:[" + pk + "]");
    }
  }

  /**
   * 启动池
   * @author 刘虻
   * 2006-8-13 14:23:28
   */
  @Override
  public void startPool() {
    if (state == 2) {
      // 防止重复启动
      return;
    }
    objectPoolHasm = new SListMap<SListMap<IObjectElement>>();
    state = 2; // 标识正在运行中
    // 构造服务线程，并启动
    oprt = new ObjectPoolRootThread(this);
    oprt.start();
  }

  /**
   * 清除指定类型下的所有元素
   * @author 刘虻
   * 2007-5-14下午01:49:00
   * @param type 指定类型
   */
  @Override
  public void clearByType(String type) {
    if (objectPoolHasm != null) {
      // 获取指定类型下的所有元素
      SListMap<IObjectElement> typeHasm = objectPoolHasm.get(type);
      if (typeHasm != null) {
        for (int i = 0; i < typeHasm.size(); i++) {
          closeElement(type, typeHasm.getKey(i));
        }
        objectPoolHasm.put(type, null);
      }
    }
  }

  /**
   * 获取所有类型序列
   * @author 刘虻
   * 2007-5-15下午07:41:55
   * @return 所有类型序列
   */
  @Override
  public List<String> getAllTypeList() {
    if (objectPoolHasm == null) {
      return new ArrayList<String>();
    }
    return objectPoolHasm.keys();
  }

  /**
   * 获取指定类型容器中，对象的数量
   * @author 刘虻
   * 2007-5-15下午07:43:47
   * @param type 类型
   * @return 对象的数量
   */
  @Override
  public int getObjectCountByType(String type) {
    if (objectPoolHasm == null) {
      return 0;
    }
    // 获取指定类型的对象容器
    SListMap<IObjectElement> objectMap = objectPoolHasm.get(type);
    if (objectMap == null) {
      return 0;
    }
    return objectMap.size();
  }

  /**
   * 清除所有内容
   * @author 刘虻
   * 2007-5-14下午01:47:04
   */
  @Override
  public void clearAllObject() {
    if (objectPoolHasm != null) {
      for (int i = 0; i < objectPoolHasm.size(); i++) {
        clearByType(objectPoolHasm.getKey(i));
      }
      objectPoolHasm = null;
    }
  }

  /**
   * 终止元素
   * @author 刘虻2006-8-13 13:48:42
   * @deprecated
   */
  @Override
  public void terminat() {
    state = 1; // 标识线程终止
    clearAllObject(); // 清空所有对象
    try {
      oprt.stop(); // 终止服务线程
    } catch (Exception e) {
    }
  }

  /**
   * 覆盖方法
   * @author 刘虻
   * 2007-3-14下午05:41:17
   */
  public int getTimeAround() {
    return timeAround;
  }

  /**
   * 覆盖方法
   * @author 刘虻
   * 2007-3-14下午05:41:23
   */
  public void setTimeAround(int timeAround) {
    this.timeAround = timeAround;
  }

  /**
   * 获取初始化类实例超时时间
   * @author 刘虻
   * 2007-8-20下午05:51:25
   * @return 初始化类实例超时时间
   */
  public long getInitObjectTimeOut() {
    return initObjectTimeOut;
  }

  /**
   * 设置初始化类实例超时时间
   * @author 刘虻
   * 2007-8-20下午05:51:33
   * @param initObjectTimeOut 初始化类实例超时时间
   */
  public void setInitObjectTimeOut(long initObjectTimeOut) {
    this.initObjectTimeOut = initObjectTimeOut;
  }

  /**
   * 判断是否存在指定类实例
   * @author 刘虻
   * 2010-5-6 下午01:05:12
   * @param type 指定类型
   * @param pk   指定主键
   * @return true存在
   */
  @Override
  public boolean hasInstance(String type, String pk) {
    if (type == null || type.length() < 1 || pk == null || pk.length() < 1 || objectPoolHasm == null) {
      return false;
    }
    // 获得指定类型的对象池容器
    SListMap<IObjectElement> thisTypeObjectPool = objectPoolHasm.get(type);
    if (thisTypeObjectPool == null) {
      return false;
    }
    return thisTypeObjectPool.containsKey(pk);
  }

  /**
   * 获取新的序列号
   * 2015年11月22日
   * @author 刘虻
   * @return 新的序列号
   */
  protected synchronized String getSID() {
    if (sn == null) {
      sn = FSN.newInstance("_object_pool_", 40);
    }
    return sn.getSID();
  }

  /**
   * 判断池中是否有该类型
   * 2010-5-6 下午01:04:02
   * @author 刘虻
   * @param type 类型值
   * @return true存在指定类型
   */
  @Override
  public boolean hasType(String type) {
    if (type == null || type.length() < 1) {
      return false;
    }
    return getObjectPoolMap().containsKey(type);
  }
}
